﻿using Newtonsoft.Json;
using Shared.Method;
using Shared.Model;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace StationTestDll
{
    public class StationTestHP
    {
        //private static YcdStrTcpClient _client = null;//TCP客户端
        private static HPSocketCS.TcpPackClient _client = null;//HP客户端

        private static Dictionary<string, string> _dictRecvMsg = null;//保存返回的信息,guid+Msg

        private static string _tcpMsg = null;
        public static string TcpMsg { get { return _tcpMsg; } }//返回信息

        private static string _tcpErrorMsg = null;
        public static string TcpErrorMsg { get { return _tcpErrorMsg; } } //返回错误

        //private static readonly object objMsgLock = new object();//错误信息锁定
        private static readonly object _objRecvLock = new object();//发送锁定
        private static readonly object _objClientLock = new object();//获取对象锁定

        /// <summary>
        /// 获取TCPClient，并保证在多线程状态下，只有一个在执行
        /// </summary>
        /// <param name="ip"></param>
        /// <param name="port"></param>
        /// <returns></returns>
        private static HPSocketCS.TcpPackClient GetTcpClient(string ip = "127.0.0.1", int port = 26398)
        {
            //if (_client != null && _client.ClientConnected()) return _client;
            if (_client != null||_client.State== HPSocketCS.ServiceState.Stoped) return _client;

            //YcdStrTcpClient client = new YcdStrTcpClient(ip, port);
            HPSocketCS.TcpPackClient client = new HPSocketCS.TcpPackClient();
            client.OnReceive += Client_OnReceive;
            client.PackHeaderFlag = SharedData.PACK_HANDER_FLAG;
            client.MaxPackSize = SharedData.MAX_PACK_SIZE;

            //client.Start();            
            //client.OnReceive += Client_OnReceive;
            //client.OnError += Client_OnError;
            _dictRecvMsg = new Dictionary<string, string>();
            if (client.Connect(ip, (ushort)port) == false)
                client = null;

            System.Threading.Thread.Sleep(500);//休息0.5秒解决第一次连接出现卡死的情况

            return client;
        }

        private static HPSocketCS.HandleResult Client_OnReceive(HPSocketCS.TcpClient sender, byte[] bytes)
        {
            var recvStr = Encoding.UTF8.GetString(bytes);

            if (string.IsNullOrEmpty(recvStr) || recvStr.Length <= 32) return HPSocketCS.HandleResult.Ok;//清除小于32个字符的数据

            string guid = recvStr.Substring(0, 32);
            string msg = recvStr.Substring(32);

            lock (_objRecvLock)
                _dictRecvMsg.Add(guid, msg);

            return HPSocketCS.HandleResult.Ok;
        }

        private static void Client_OnError(string obj)
        {
            _tcpErrorMsg = obj;
        }

        //private static void Client_OnReceive(string obj)
        //{
        //    if (string.IsNullOrEmpty(obj) || obj.Length <= 32) return;//清除小于32个字符的数据

        //    string guid = obj.Substring(0, 32);
        //    string msg = obj.Substring(32);

        //    lock (_objRecvLock)
        //        _dictRecvMsg.Add(guid, msg);
        //}

        /// <summary>
        /// 是否能够测试
        /// </summary>
        /// <param name="productMac"></param>
        /// <returns></returns>
        public static bool IfCanTest(string productMac, ref string msg, string serverIp = "127.0.0.1")
        {
            ReturnMessage canTestMsg = new ReturnMessage()
            {
                ProductMac = productMac
            };

            //获取唯一标识和发送数据
            string guid = Guid.NewGuid().ToString("N");

            //return SendAndRecvMsg(serverIp, 26398, SharedData.CAN_TEST, guid, JsonConvert.SerializeObject(canTestMsg), ref msg);

            lock (_objClientLock)
            {
                SendMsg(SharedData.CAN_TEST, guid, JsonConvert.SerializeObject(canTestMsg), serverIp);
                return GetResult(guid, ref msg);
            }
        }
        /// <summary>
        /// 返回测试结果
        /// </summary>
        /// <param name="productMac"></param>
        /// <param name="result"></param>
        /// <returns></returns>
        private static bool ReturnTestResult(string productMac, bool result, ref string msg, string serverIp = "127.0.0.1")
        {
            TestResultMsg testResult = new TestResultMsg()
            {
                ProductMac = productMac,
                TestResult = result
            };

            //获取唯一标识和发送数据
            string guid = Guid.NewGuid().ToString("N");

            //return SendAndRecvMsg(serverIp, 26398, SharedData.TEST_RESULT, guid, JsonConvert.SerializeObject(testResult), ref msg);

            SendMsg(SharedData.TEST_RESULT, guid, JsonConvert.SerializeObject(testResult), serverIp);
            return GetResult(guid, ref msg);
        }

        /// <summary>
        /// 写测试数据
        /// </summary>
        /// <param name="productMac">产品MAC</param>
        /// <param name="result">测试结果</param>
        /// <param name="testLog">测试LOG</param>
        /// <returns></returns>
        public static bool SaveTestData(string productMac, bool result, string testLog, ref string msg, string serverIp = "127.0.0.1")
        {
            TestSaveLog saveMsg = new TestSaveLog()
            {
                ProductMac = productMac,
                TestResult = result,
                TestLog = testLog
            };

            //获取唯一标识和发送数据
            string guid = Guid.NewGuid().ToString("N");

            //if (ReturnTestResult(productMac, result, ref msg, serverIp) == false)
            //{
            //    return false;
            //}

            //SendAndRecvMsg(serverIp, 26398, SharedData.SAVE_TEST_DATA, guid, JsonConvert.SerializeObject(saveMsg), ref msg);

            //return true;

            lock (_objClientLock)
            {
                //添加写过程信息的内容到此处，节省一些代码
                if (ReturnTestResult(productMac, result, ref msg, serverIp) == false)
                {
                    return false;
                }

                SendMsg(SharedData.SAVE_TEST_DATA, guid, JsonConvert.SerializeObject(saveMsg), serverIp);

                //查找接收的数据中是否有GUID内容
                return GetResult(guid, ref msg);
            }
        }

        /// <summary>
        /// 获取和服务端沟通的结果
        /// </summary>
        /// <param name="guid"></param>
        /// <returns></returns>
        private static bool GetResult(string guid, ref string msg)
        {
            //查找接收的数据中是否有GUID内容
            //if (_client.ClientConnected() == false) { msg = _tcpErrorMsg; return false; }
            //if (_client.State == HPSocketCS.ServiceState.Stoped) { msg = _tcpErrorMsg;return false; }

            int i = 0;
            ReturnMessage retMsg = null;
            for (; i < SharedData.WAIT_TIMES; i++)
            {
                System.Threading.Thread.Sleep(500);
                string recvMsg = null;

                if (_dictRecvMsg.ContainsKey(guid) && _dictRecvMsg.TryGetValue(guid, out recvMsg))//判断是否有guid，并导出value
                {
                    retMsg = JsonConvert.DeserializeObject<ReturnMessage>(recvMsg);
                    _dictRecvMsg.Remove(guid);
                    break;
                }
            }

            msg = "";

            if (i == SharedData.WAIT_TIMES) { msg = "未能获得回传信息"; return false; }

            msg = retMsg.Message;//获取返回信息

            if (retMsg.RetResult)
            {
                _tcpMsg = retMsg.Message;
                return true;//可以测试则返回true
            }
            else
            {
                if (string.IsNullOrEmpty(msg)) msg = "未能获取回传信息";
                return false;
            }
        }

        /// <summary>
        /// 发送消息的方法
        /// </summary>
        /// <param name="type">请求类型</param>
        /// <param name="guid">请求GUID</param>
        /// <param name="msg">具体数据</param>
        private static void SendMsg(string type, string guid, string msg, string serverIp)
        {
            _client = GetTcpClient(serverIp);
            //_client.SendData(string.Format("{0}{1}{2}", type, guid, msg));
            var sendBytes = Encoding.UTF8.GetBytes(string.Format("{0}{1}{2}", type, guid, msg));
            _client.Send(sendBytes, sendBytes.Length);
        }

        #region 使用新方法获取数据

        public static bool SendAndRecvMsg(string ip, int port, string type, string guid, string sendMsg, ref string outputMsg)
        {
            try
            {
                #region hpsocket
                //tcppackclient

                #endregion

                string recvMsg = StaticTcpClient.SendAndRecvStr(ip, port, string.Format("{0}{1}{2}", type, guid, sendMsg));

                if (string.IsNullOrEmpty(recvMsg) || recvMsg.Length <= 32) return false;//清除小于32个字符的数据

                if (guid == recvMsg.Substring(0, 32))
                {
                    var strClass = recvMsg.Substring(32);

                    var retMsg = JsonConvert.DeserializeObject<ReturnMessage>(strClass);

                    outputMsg = retMsg.Message;

                    return retMsg.RetResult;
                }
                else
                {
                    outputMsg = "获取数据失败";
                    return false;
                }
            }
            catch (Exception ex)
            {
                outputMsg = ex.ToString();
                return false;
            }
        }
        #endregion
    }
}
